import 'dart:io';
import 'package:flutter/material.dart';
import 'package:audioplayers/audioplayers.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:file_picker/file_picker.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() {
  runApp(const MusicPlayerApp());
}

class MusicPlayerApp extends StatelessWidget {
  const MusicPlayerApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Music Player',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MusicPlayerHomePage(),
      debugShowCheckedModeBanner: false,
    );
  }
}

class MusicPlayerHomePage extends StatefulWidget {
  const MusicPlayerHomePage({super.key});

  @override
  State<MusicPlayerHomePage> createState() => _MusicPlayerHomePageState();
}

class _MusicPlayerHomePageState extends State<MusicPlayerHomePage> {
  final AudioPlayer _audioPlayer = AudioPlayer();
  String _musicDirPath = 'E:/Music';
  List<FileSystemEntity> _musicFiles = [];
  int _currentIndex = 0;
  List<LrcLine> _lyrics = [];
  int _currentLyricIndex = 0;
  bool _isPlaying = false;
  bool _isShuffle = false;
  bool _isLoop = true;
  Duration _position = Duration.zero;
  Duration _duration = Duration.zero;
  double _volume = 1.0;

  @override
  void initState() {
    super.initState();
    _init();
    _audioPlayer.onPositionChanged.listen((pos) {
      setState(() {
        _position = pos;
        _updateCurrentLyricIndex();
      });
    });
    _audioPlayer.onDurationChanged.listen((dur) {
      setState(() {
        _duration = dur ?? Duration.zero;
      });
    });
    _audioPlayer.onPlayerStateChanged.listen((state) {
      setState(() {
        _isPlaying = state == PlayerState.playing;
      });
    });
    _audioPlayer.onPlayerComplete.listen((event) {
      _onSongComplete();
    });
  }

  Future<void> _pickMusicDir() async {
    String? selectedDir = await FilePicker.platform.getDirectoryPath(dialogTitle: '选择音乐目录');
    if (selectedDir != null && selectedDir.isNotEmpty) {
      setState(() {
        _musicDirPath = selectedDir;
      });
      await _init();
    }
  }

  Future<void> _init() async {
    await Permission.storage.request();
    final musicDir = Directory(_musicDirPath);
    if (await musicDir.exists()) {
      final files = musicDir
          .listSync()
          .where((f) => f.path.endsWith('.mp3') || f.path.endsWith('.flac') || f.path.endsWith('.wav'))
          .toList();
      setState(() {
        _musicFiles = files;
      });
    }
  }

  Future<void> _loadAndPlay(int index) async {
    if (index < 0 || index >= _musicFiles.length) return;
    final file = _musicFiles[index];
    await _audioPlayer.stop();
    await _audioPlayer.play(DeviceFileSource(file.path));
    setState(() {
      _currentIndex = index;
      _position = Duration.zero;
      _lyrics = [];
      _currentLyricIndex = 0;
    });
    await _loadLyrics(file);
  }

  Future<void> _loadLyrics(FileSystemEntity musicFile) async {
    final musicName = musicFile.uri.pathSegments.last;
    final baseName = musicName.replaceAll(RegExp(r'\.(mp3|flac|wav)'), '');
    final lrcPath = '$_musicDirPath/Lyrics/$baseName.lrc';
    final lrcFile = File(lrcPath);
    if (await lrcFile.exists()) {
      final content = await lrcFile.readAsString();
      setState(() {
        _lyrics = parseLrc(content);
      });
    } else {
      setState(() {
        _lyrics = [];
      });
    }
  }

  void _updateCurrentLyricIndex() {
    if (_lyrics.isEmpty) return;
    for (int i = 0; i < _lyrics.length; i++) {
      if (_position < _lyrics[i].time) {
        _currentLyricIndex = i == 0 ? 0 : i - 1;
        return;
      }
    }
    _currentLyricIndex = _lyrics.length - 1;
  }

  void _onSongComplete() {
    if (_isShuffle) {
      final next = (List.generate(_musicFiles.length, (i) => i)..remove(_currentIndex))..shuffle();
      _loadAndPlay(next.first);
    } else if (_isLoop) {
      _loadAndPlay((_currentIndex + 1) % _musicFiles.length);
    }
  }

  Future<void> _downloadMusicById(String id) async {
    try {
      final response = await http.post(
        Uri.parse('http://www.78497.com/style/js/play.php'),
        headers: {
          'Referer': 'http://www.78497.com/mp3/$id.html',
        },
        body: {'id': id, 'type': 'dance'},
      );
      if (response.statusCode == 200) {
        final data = response.body;
        final json = jsonDecode(data);
        if (json['msg'] == 1) {
          final name = json['name'] ?? '未知歌曲';
          final singer = json['singer'] ?? '未知歌手';
          final url = json['url'];
          final lrc = json['lrc'] ?? '';
          final pic = json['pic'] ?? '';
          // 保存音乐
          final musicName = '$name-$singer.mp3';
          final musicFile = File('$_musicDirPath/$musicName');
          if (await musicFile.exists()) {
            if (mounted) {
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('本地已存在: $musicName')),
              );
            }
            return;
          }
          final musicRes = await http.get(Uri.parse(url));
          await musicFile.writeAsBytes(musicRes.bodyBytes);
          // 保存歌词
          if (lrc.isNotEmpty) {
            final lrcDir = Directory('$_musicDirPath/Lyrics');
            if (!await lrcDir.exists()) await lrcDir.create(recursive: true);
            final lrcFile = File('${lrcDir.path}/$name-$singer.lrc');
            await lrcFile.writeAsString(lrc);
          }
          // 保存头像
          if (pic.isNotEmpty) {
            final imgDir = Directory('$_musicDirPath/Images');
            if (!await imgDir.exists()) await imgDir.create(recursive: true);
            final ext = pic.split('.').last.split('?').first;
            final imgFile = File('${imgDir.path}/$singer.$ext');
            final imgRes = await http.get(Uri.parse(pic));
            await imgFile.writeAsBytes(imgRes.bodyBytes);
          }
          // 刷新列表
          await _init();
          if (mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              SnackBar(content: Text('下载成功: $name-$singer')),
            );
          }
        } else {
          if (mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('未找到该编号对应的音乐')),
            );
          }
        }
      } else {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('请求失败')),
          );
        }
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('下载出错: $e')),
        );
      }
    }
  }

  @override
  void dispose() {
    _audioPlayer.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Column(
          children: [
            // 顶部选择目录栏
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
              child: Row(
                children: [
                  ElevatedButton.icon(
                    onPressed: _pickMusicDir,
                    icon: const Icon(Icons.folder_open),
                    label: const Text('选择音乐目录'),
                  ),
                  const SizedBox(width: 16),
                  Expanded(
                    child: Text(
                      '当前目录: $_musicDirPath',
                      style: const TextStyle(fontSize: 14, color: Colors.black54),
                      overflow: TextOverflow.ellipsis,
                    ),
                  ),
                  IconButton(
                    icon: const Icon(Icons.download),
                    tooltip: '通过编号下载音乐',
                    onPressed: () async {
                      final id = await showDialog<String>(
                        context: context,
                        builder: (context) {
                          String input = '';
                          return AlertDialog(
                            title: const Text('下载音乐'),
                            content: TextField(
                              autofocus: true,
                              decoration: const InputDecoration(
                                hintText: '输入www.78497.com音乐编号将自动下载音乐到列表',
                              ),
                              onChanged: (v) => input = v,
                              onSubmitted: (v) => Navigator.of(context).pop(v),
                            ),
                            actions: [
                              TextButton(
                                onPressed: () => Navigator.of(context).pop(input),
                                child: const Text('确定'),
                              ),
                              TextButton(
                                onPressed: () => Navigator.of(context).pop(),
                                child: const Text('取消'),
                              ),
                            ],
                          );
                        },
                      );
                      if (id != null && id.trim().isNotEmpty) {
                        await _downloadMusicById(id.trim());
                      }
                    },
                  ),
                  IconButton(
                    icon: const Icon(Icons.refresh),
                    tooltip: '刷新歌曲列表',
                    onPressed: _init,
                  ),
                ],
              ),
            ),
            Expanded(
              child: Row(
                children: [
                  // 左侧音乐列表
                  Expanded(
                    flex: 2,
                    child: MusicListWidget(
                      musicFiles: _musicFiles,
                      currentIndex: _currentIndex,
                      onTap: (i) => _loadAndPlay(i),
                      onDelete: (i) async {
                        final file = _musicFiles[i];
                        final name = file.uri.pathSegments.last;
                        // 删除音乐文件
                        await file.delete();
                        // 删除歌词文件
                        final baseName = name.replaceAll(RegExp(r'\.(mp3|flac|wav)'), '');
                        final lrcFile = File('$_musicDirPath/Lyrics/$baseName.lrc');
                        if (await lrcFile.exists()) {
                          await lrcFile.delete();
                        }
                        // 如果删除的是当前播放歌曲，停止播放并重置状态
                        if (i == _currentIndex) {
                          await _audioPlayer.stop();
                          setState(() {
                            _isPlaying = false;
                            _position = Duration.zero;
                            _duration = Duration.zero;
                            _lyrics = [];
                            _currentLyricIndex = 0;
                          });
                        } else if (i < _currentIndex && _currentIndex > 0) {
                          // 如果删除的是当前播放前面的歌曲，索引前移
                          setState(() {
                            _currentIndex -= 1;
                          });
                        }
                        await _init();
                        if (mounted) {
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(content: Text('已删除: $name')),
                          );
                        }
                      },
                    ),
                  ),
                  // 右侧主内容区
                  Expanded(
                    flex: 5,
                    child: Column(
                      children: [
                        // 歌曲封面+信息
                        SongInfoWidget(
                          file: _musicFiles.isNotEmpty ? _musicFiles[_currentIndex] : null,
                          musicDirPath: _musicDirPath,
                        ),
                        // 歌词区
                        Expanded(
                          child: LyricsWidget(
                            lyrics: _lyrics,
                            currentIndex: _currentLyricIndex,
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
            // 底部播放控制栏
            PlaybackBarWidget(
              isPlaying: _isPlaying,
              position: _position,
              duration: _duration,
              onPlayPause: () {
                if (_isPlaying) {
                  _audioPlayer.pause();
                } else {
                  _audioPlayer.resume();
                }
              },
              onNext: () => _loadAndPlay((_currentIndex + 1) % _musicFiles.length),
              onPrev: () => _loadAndPlay((_currentIndex - 1 + _musicFiles.length) % _musicFiles.length),
              onSeek: (v) => _audioPlayer.seek(Duration(seconds: v.toInt())),
              isShuffle: _isShuffle,
              isLoop: _isLoop,
              onToggleShuffle: () => setState(() => _isShuffle = !_isShuffle),
              onToggleLoop: () => setState(() => _isLoop = !_isLoop),
              volume: _volume,
              onVolumeChanged: (v) {
                setState(() => _volume = v);
                _audioPlayer.setVolume(v);
              },
            ),
          ],
        ),
      ),
    );
  }
}

class MusicListWidget extends StatelessWidget {
  final List<FileSystemEntity> musicFiles;
  final int currentIndex;
  final Function(int) onTap;
  final Function(int) onDelete;
  const MusicListWidget({super.key, required this.musicFiles, required this.currentIndex, required this.onTap, required this.onDelete});
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey[100],
      child: ListView.builder(
        itemCount: musicFiles.length,
        itemBuilder: (context, index) {
          final name = musicFiles[index].uri.pathSegments.last;
          return GestureDetector(
            onSecondaryTapDown: (details) async {
              final selected = await showMenu<String>(
                context: context,
                position: RelativeRect.fromLTRB(
                  details.globalPosition.dx,
                  details.globalPosition.dy,
                  details.globalPosition.dx,
                  details.globalPosition.dy,
                ),
                items: [
                  const PopupMenuItem<String>(
                    value: 'delete',
                    child: Text('删除'),
                  ),
                ],
              );
              if (selected == 'delete') {
                onDelete(index);
              }
            },
            child: ListTile(
              leading: const Icon(Icons.music_note),
              title: Text(name),
              selected: index == currentIndex,
              onTap: () => onTap(index),
            ),
          );
        },
      ),
    );
  }
}

class SongInfoWidget extends StatelessWidget {
  final FileSystemEntity? file;
  final String musicDirPath;
  const SongInfoWidget({super.key, this.file, required this.musicDirPath});
  @override
  Widget build(BuildContext context) {
    String name = file != null ? file!.uri.pathSegments.last : '无歌曲';
    String title = name;
    String artist = '未知歌手';
    if (file != null && name.contains('-')) {
      final parts = name.split('-');
      title = parts[0].trim();
      artist = parts.sublist(1).join('-').replaceAll(RegExp(r'\.(mp3|flac|wav)'), '').trim();
    } else if (file != null) {
      title = name.replaceAll(RegExp(r'\.(mp3|flac|wav)'), '').trim();
    }
    // 尝试加载头像
    File? imgFile;
    if (artist != '未知歌手') {
      final imgDir = Directory('$musicDirPath/Images');
      if (imgDir.existsSync()) {
        // 只取歌手名部分，去除扩展名
        final artistName = artist.replaceAll(RegExp(r'\.(mp3|flac|wav|jpg|png|jpeg)'), '').trim();
        final files = imgDir
            .listSync()
            .where((f) => f is File && f.path.split(Platform.pathSeparator).last.startsWith('$artistName.'))
            .toList();
        if (files.isNotEmpty) {
          imgFile = File(files.first.path);
        }
      }
    }
    return Padding(
      padding: const EdgeInsets.all(24.0),
      child: Row(
        children: [
          ClipRRect(
            borderRadius: BorderRadius.circular(12),
            child: imgFile != null && imgFile.existsSync()
                ? Image.file(imgFile, width: 100, height: 100, fit: BoxFit.cover)
                : Container(
                    color: Colors.grey[300],
                    width: 100,
                    height: 100,
                    child: const Icon(Icons.album, size: 60),
                  ),
          ),
          const SizedBox(width: 24),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(title, style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold)),
              const SizedBox(height: 8),
              Text(artist, style: const TextStyle(fontSize: 16, color: Colors.grey)),
            ],
          ),
        ],
      ),
    );
  }
}

class LyricsWidget extends StatefulWidget {
  final List<LrcLine> lyrics;
  final int currentIndex;
  const LyricsWidget({super.key, required this.lyrics, required this.currentIndex});

  @override
  State<LyricsWidget> createState() => _LyricsWidgetState();
}

class _LyricsWidgetState extends State<LyricsWidget> {
  final ScrollController _scrollController = ScrollController();

  @override
  void didUpdateWidget(covariant LyricsWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.currentIndex != oldWidget.currentIndex) {
      _scrollToCurrent();
    }
  }

  void _scrollToCurrent() {
    if (widget.currentIndex < 0 || widget.currentIndex >= widget.lyrics.length) return;
    // 每行高度约28，居中显示
    final offset = (widget.currentIndex * 28.0) - 100;
    _scrollController.animateTo(
      offset < 0 ? 0 : offset,
      duration: const Duration(milliseconds: 300),
      curve: Curves.easeInOut,
    );
  }

  @override
  Widget build(BuildContext context) {
    if (widget.lyrics.isEmpty) {
      return const Center(child: Text('无歌词'));
    }
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 16),
      child: ListView.builder(
        controller: _scrollController,
        itemCount: widget.lyrics.length,
        itemBuilder: (context, i) {
          final line = widget.lyrics[i];
          return Padding(
            padding: const EdgeInsets.symmetric(vertical: 4),
            child: Text(
              line.text,
              style: TextStyle(
                fontSize: i == widget.currentIndex ? 22 : 16,
                color: i == widget.currentIndex ? Colors.red : Colors.black87,
                fontWeight: i == widget.currentIndex ? FontWeight.bold : FontWeight.normal,
              ),
              textAlign: TextAlign.center,
            ),
          );
        },
      ),
    );
  }
}

class PlaybackBarWidget extends StatelessWidget {
  final bool isPlaying;
  final Duration position;
  final Duration duration;
  final VoidCallback onPlayPause;
  final VoidCallback onNext;
  final VoidCallback onPrev;
  final ValueChanged<double> onSeek;
  final bool isShuffle;
  final bool isLoop;
  final VoidCallback onToggleShuffle;
  final VoidCallback onToggleLoop;
  final double volume;
  final ValueChanged<double> onVolumeChanged;
  const PlaybackBarWidget({
    super.key,
    required this.isPlaying,
    required this.position,
    required this.duration,
    required this.onPlayPause,
    required this.onNext,
    required this.onPrev,
    required this.onSeek,
    required this.isShuffle,
    required this.isLoop,
    required this.onToggleShuffle,
    required this.onToggleLoop,
    required this.volume,
    required this.onVolumeChanged,
  });
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
      child: Row(
        children: [
          IconButton(
            icon: const Icon(Icons.skip_previous),
            onPressed: onPrev,
          ),
          IconButton(
            icon: Icon(isPlaying ? Icons.pause : Icons.play_arrow),
            onPressed: onPlayPause,
          ),
          IconButton(
            icon: const Icon(Icons.skip_next),
            onPressed: onNext,
          ),
          const SizedBox(width: 16),
          // 进度条
          Expanded(
            child: Slider(
              value: position.inSeconds.toDouble(),
              max: duration.inSeconds > 0 ? duration.inSeconds.toDouble() : 1,
              onChanged: onSeek,
            ),
          ),
          const SizedBox(width: 16),
          // 音量调节
          const Icon(Icons.volume_up),
          SizedBox(
            width: 100,
            child: Slider(
              value: volume,
              min: 0.0,
              max: 1.0,
              onChanged: onVolumeChanged,
            ),
          ),
          const SizedBox(width: 16),
          IconButton(
            icon: Icon(isLoop ? Icons.repeat : Icons.repeat_one),
            onPressed: onToggleLoop,
          ),
          IconButton(
            icon: Icon(isShuffle ? Icons.shuffle_on : Icons.shuffle),
            onPressed: onToggleShuffle,
          ),
        ],
      ),
    );
  }
}

// 歌词解析
class LrcLine {
  final Duration time;
  final String text;
  LrcLine(this.time, this.text);
}

List<LrcLine> parseLrc(String content) {
  final lines = content.split('\n');
  final result = <LrcLine>[];
  final reg = RegExp(r'\[(\d+):(\d+)(?:\.(\d+))?\](.*)');
  for (var line in lines) {
    final match = reg.firstMatch(line);
    if (match != null) {
      final min = int.parse(match.group(1)!);
      final sec = int.parse(match.group(2)!);
      final ms = match.group(3) != null ? int.parse(match.group(3)!.padRight(3, '0')) : 0;
      final text = match.group(4)!.trim();
      result.add(LrcLine(Duration(minutes: min, seconds: sec, milliseconds: ms), text));
    }
  }
  result.sort((a, b) => a.time.compareTo(b.time));
  return result;
}
